package points_logic

import (
	"context"
	"errors"
	"fmt"
	"time"
	"wx-uniapp-go/internal/repository/dto"
	"wx-uniapp-go/internal/repository/models"
)

type PointsLogic struct {
	Ctx context.Context
}

func NewPointsLogic(ctx context.Context) *PointsLogic {
	return &PointsLogic{Ctx: ctx}
}

// ChangePoints 变更积分
func (l *PointsLogic) ChangePoints(req *dto.PointsChangeReq) (err error) {
	ctx := l.Ctx

	// 获取积分规则
	rule := new(models.PointsRule)
	exists, err := models.Get(ctx, rule, "type = ? AND status = 1", req.Type)
	if err != nil {
		return err
	}
	if !exists {
		return errors.New("无效的积分类型")
	}

	// 如果没有指定积分值，使用规则配置的值
	if req.Points == 0 {
		req.Points = rule.Points
	}

	// 检查每日限制
	if rule.DayLimit > 0 {
		count, err := l.getTodayActionCount(req.UserId, req.Type)
		if err != nil {
			return err
		}
		if count >= rule.DayLimit {
			return errors.New("已达到每日限制次数")
		}
	}

	// 开启事务
	ctx = models.BeginTransaction(ctx)

	// 获取或创建用户积分记录
	userPoints := new(models.UserPoints)
	exists, err = models.Get(ctx, userPoints, "user_id = ?", req.UserId)
	if err != nil {
		return
	}

	if !exists {
		userPoints = &models.UserPoints{
			UserId: req.UserId,
		}
		if _, err = models.Insert(ctx, userPoints); err != nil {
			return err
		}
	}

	// 更新积分
	userPoints.Points += req.Points
	if req.Points > 0 {
		userPoints.TotalPoints += req.Points
	}

	if err = models.Update(ctx, fmt.Sprintf("user_id = %d", req.UserId), userPoints); err != nil {
		return
	}

	// 记录积分日志
	pointsLog := &models.UserPointsLog{
		UserId:     req.UserId,
		Type:       req.Type,
		Points:     req.Points,
		Balance:    userPoints.Points,
		Remark:     req.Remark,
		OperatorId: req.Operator,
	}

	if _, err = models.Insert(ctx, pointsLog); err != nil {
		return
	}

	return
}

// getTodayActionCount 获取今日某类型操作次数
func (l *PointsLogic) getTodayActionCount(userId int64, actionType string) (int, error) {
	today := time.Now().Format("2006-01-02")
	count, err := models.Count(l.Ctx, &models.UserPointsLog{},
		"user_id = ? AND type = ? AND DATE(create_time) = ?",
		userId, actionType, today)
	return int(count), err
}

// GetPointsRules 获取积分规则列表
func (l *PointsLogic) GetPointsRules() ([]*dto.PointsRuleResp, error) {
	var rules []*models.PointsRule
	err := models.Find(l.Ctx, &rules, "status = 1")
	if err != nil {
		return nil, err
	}

	resp := make([]*dto.PointsRuleResp, len(rules))
	for i, rule := range rules {
		resp[i] = &dto.PointsRuleResp{
			Type:        rule.Type,
			Name:        rule.Name,
			Points:      rule.Points,
			DayLimit:    rule.DayLimit,
			Description: rule.Description,
		}
	}
	return resp, nil
}

// GetUserPoints 获取用户积分
func (l *PointsLogic) GetUserPoints(userId int64) (*dto.UserPointsResp, error) {
	userPoints := new(models.UserPoints)
	exists, err := models.Get(l.Ctx, userPoints, "user_id = ?", userId)
	if err != nil {
		return nil, err
	}

	if !exists {
		return &dto.UserPointsResp{}, nil
	}

	return &dto.UserPointsResp{
		Points:      userPoints.Points,
		TotalPoints: userPoints.TotalPoints,
	}, nil
}
